//
//  MainMenu.swift
//  Speek
//
//  Created by MikeHo on 2023/4/18.
//

import SwiftUI
import Speech

struct MainMenu: View {
    @State private var isRecording = false
    @State private var isEditing = false
    @State private var text = ""
    @State var isShowingImage = true
    @State var isPresented = false
    @State private var isLoading = false
    @State private var isSuccess = false
    @State private var isShowingResult = false
    @State private var audioEngine: AVAudioEngine!
    @State private var speechRecognizer: SFSpeechRecognizer!
    @State private var request: SFSpeechAudioBufferRecognitionRequest!
    @State private var recognitionTask: SFSpeechRecognitionTask!
    @State private var outputText = ""
    
    //编辑取消相关变量
    @State private var isEditScaled = false
    @State private var isEditingText = false
    @State private var isCancelScaled = false
    @State private var isEditFinished = false
    let dragOffset :CGFloat = -70
    
    //震动
    let generator = UIImpactFeedbackGenerator(style: .heavy)
    
    @Environment(\.managedObjectContext) private var context
    
    var body: some View {
        
        ZStack{
            VStack{
                
                VStack(alignment: .center){
                    
                    //logo与语音转文字的文本框切换
                    if isShowingImage{
                        
                        VStack{
                            Text("You")
                            Text("Speak,")
                            Text("We")
                            Text("Keep.")
                        }
                        .font(.system(size: 50))
                        .bold()
                        .padding(.top,150)
                        
                    }else{
                        if isEditingText{
                            VStack{
                                TextField(text,text:$text)
                                    .textFieldStyle(RoundedTextFieldStyle())
                                    .transition(.opacity)
                                    .foregroundColor(.black)
                                    //.background(Color.white.opacity(0.8))
                                    .onSubmit {
                                        // 处理按下键盘的提交按钮时的逻辑
                                        isEditingText = false
                                        chatWithAPI()
                                    }
                                Spacer()
                                Button (action:{
                                    
                                })
                                {
                                    Image(systemName: "checkmark.circle")
                                        .foregroundColor(.white)
                                        .font(.system(size: 155))
                                        .padding()
                                        .offset(y:-40)
                                        
                                }
                                .transition(.opacity)
                                .offset(y:-105)
                                .onLongPressGesture(minimumDuration: 0, pressing: {pressing in
                                    if pressing{
                                        isEditFinished = true ;
                                        
                                    }
                                    else{
                                        isEditFinished = false ;
                                        isEditingText = false
                                        chatWithAPI()
                                        generator.impactOccurred()
                                        //stopRecording()
                                    }
                                }){}
                                    .scaleEffect(isEditFinished ? 0.7 : 1 )
                                    .animation(.easeInOut(duration: 0.2))

                            }
                            .onAppear
                            {
                                withAnimation(.easeInOut(duration: 1.0))
                                {}
                            }
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.black.opacity(0.5))
                            .ignoresSafeArea(.all)
                            .font(.system(size: 30))
                            .padding(.top,200)
                            .padding(.horizontal,10)
                        }else{
                            Text(text)
                                .foregroundColor(.white)
                                .font(.system(size: 30))
                                .frame(height:200)
                                .padding(.top,200)
                                .padding(.horizontal,10)
                        }
                    }
                    
                    Spacer()
                    
                    if !isEditingText{
                    HStack {
                        Spacer()
                        Button(action: {
                            // Cancel recording
                        }) {
                            Image("Cancel")
                                .resizable()
                                .frame(width: 70, height: 70)
                                .foregroundColor(.red)
                                .padding()
                                .opacity(isRecording ? 1 : 0)
                                .scaleEffect(isRecording ? 1 : 0.1)
                                .scaleEffect(isCancelScaled ? 1.5 : 1)
                                .animation(.easeInOut(duration: 0.5))
                        }
                        
                        Spacer()
                        Button(action: {
                            self.isEditing.toggle()
                            // Stop recording
                            // Stop speech-to-text conversion
                        }) {
                            Image("Edit")
                                .resizable()
                                .frame(width: 70, height: 70)
                                .foregroundColor(.red)
                                .padding()
                                .opacity(isRecording ? 1 : 0)
                                .scaleEffect(isRecording ? 1 : 0.1)
                                .scaleEffect(isEditScaled ? 1.5 : 1)
                                .animation(.easeInOut(duration: 0.5))
                        }
                        
                        Spacer()
                    }

                    //语音按键
                        VStack{
                            Spacer()
                            Button(action:{
                                
                                //isShowingImage = true
                            })
                            {
                                Image(isShowingImage ? "idle":"speaking")
                                    .clipShape(Circle())
                                    .aspectRatio(contentMode: .fit)
                                    .frame(height: 200)
                                    .animation(.default)
                                    .offset(y:-39)
                            }
                            
                            .onLongPressGesture(minimumDuration: 0.3, pressing: {pressing in
                                if pressing{
                                    isShowingImage = false
                                    generator.impactOccurred()
                                    startRecording()
                                }
                                else{
                                    generator.impactOccurred()
                                    //stopRecording()
                                }
                            }){}
                            
                                .simultaneousGesture(DragGesture(minimumDistance: 0)
                                    .onChanged{value in
                                        
                                        if(value.translation.height<dragOffset && value.translation.width < 0){
                                            print("CANCEL")
                                            isEditScaled = false
                                            isCancelScaled = true
                                        }
                                        else if(value.translation.height<dragOffset && value.translation.width > 0){
                                            isCancelScaled = false
                                            isEditScaled = true
                                        }
                                        else
                                        {
                                            print("NOOOO")
                                            isCancelScaled = false
                                            isEditScaled = false
                                        }
                                    }
                                    .onEnded{value in
                                        //取消功能
                                        if(value.translation.height<dragOffset && value.translation.width < 0){
                                            cancelRecording()
                                        }
                                        //编辑功能
                                        else if(value.translation.height<dragOffset && value.translation.width > 0){
                                            stopRecording()
                                            isEditingText = true
                                        }else{
                                            stopRecording()
                                            chatWithAPI()
                                        }
                                    })
                        }
                            
                        //上滑跳转图标
                        HStack{
                            
                            Spacer()
                            Image("Jump")
                                .aspectRatio(contentMode: .fit)
                                .contentShape(Rectangle())
                                .onTapGesture {
                                    isPresented = true
                                }
                            Spacer()
                        }
                        .padding(.bottom,20)
                        
                        .frame(height: 80)
                        .gesture(
                            DragGesture(minimumDistance: 100)
                                .onEnded{value in
                                    if(value.translation.height<0){
                                        isPresented = true
                                    }
                                }
                        )
                    }
                }
            }.background(Image("BackgroundImage").ignoresSafeArea().offset(y:285))
            .onAppear(perform: setupSpeech)
            .preferredColorScheme(.dark)
            .toolbar(.hidden)
            .ignoresSafeArea(.all)
            .fullScreenCover(isPresented: $isPresented, content: {
                SecondView()
            })
            
            if isShowingResult {
                if isLoading{
                    LoadingView
                }else{
                    if isSuccess{
                        SuccessView
                    }else{
                        FailView
                    }
                }
            }
        }
         
    }
    struct RoundedTextFieldStyle: TextFieldStyle {
        func _body(configuration: TextField<Self._Label>) -> some View {
            configuration
                .padding(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
                .background(Color.white)
                .cornerRadius(8)
                .shadow(color: Color.gray.opacity(0.4), radius: 3, x: 1, y: 2)
        }
    }
    
    //录音初始化
    func setupSpeech() {
        audioEngine = AVAudioEngine()
        speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))
        request = SFSpeechAudioBufferRecognitionRequest()
        text=""
    }

    //开始录音并转文字
    func startRecording() {
        request = SFSpeechAudioBufferRecognitionRequest()
        let node = audioEngine.inputNode
        let recordingFormat = node.outputFormat(forBus: 0)
        node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
            self.request.append(buffer)
        }

        audioEngine.prepare()
        do {
            try audioEngine.start()
        } catch {
            print("Error starting audio engine")
        }

        recognitionTask = speechRecognizer.recognitionTask(with: request) { result, error in
            if let result = result {
                self.text = result.bestTranscription.formattedString
            }
        }

        isRecording = true
        
       
        print("recording start")
    }

    //停止录音并将语句与api通信，获取返回数据存入CoreData中
    func stopRecording() {
        audioEngine.stop()
        audioEngine.inputNode.removeTap(onBus: 0)
        request.endAudio()
        request = nil
        recognitionTask.cancel()
        recognitionTask?.finish()
        recognitionTask = nil
        isRecording = false
    }
    
    func chatWithAPI(){
        //输入完成，进入loading动画
        isShowingResult = true
        isLoading = true
        print(text)
        print("recording stop")
        chatWithGPT(inputText: text,context: context){result in
            if result{
                isSuccess = true
            }else{
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                    isSuccess = false
                }
            }
            
            if isSuccess{
                isLoading = false
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    isShowingResult = false
                    isShowingImage = true
                }
            }else{
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                    isLoading = false
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        isShowingResult = false
                        isShowingImage = true
                    }
                }
            }
        }
        print("通信,启动")
    }
    
    func cancelRecording() {
        audioEngine.stop()
        audioEngine.inputNode.removeTap(onBus: 0)
        request.endAudio()
        request = nil
        recognitionTask.cancel()
        recognitionTask?.finish()
        recognitionTask = nil
        isRecording = false
        isShowingImage = true
        text = ""
        print("取消，启动！")
    }
}

extension MainMenu {
    var SuccessView: some View {
        
        VStack{
            Image(systemName: "checkmark.circle")
                .font(.system(size: 30))
                .foregroundColor(.green)
                .padding()
            Text("账单添加成功")
                .font(.title)
                .foregroundColor(.green)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.5).cornerRadius(20))
        .ignoresSafeArea(.all)
    }
}

extension MainMenu {
    var LoadingView: some View {
        
        VStack{
            ProgressView("添加中...")
                .font(.title)
                .progressViewStyle(CircularProgressViewStyle(tint: .orange))
                .foregroundColor(.orange)
                .cornerRadius(10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.5).cornerRadius(20))
        .ignoresSafeArea(.all)
    }
}

extension MainMenu {
    var FailView: some View {
        
        VStack{
            Image(systemName: "xmark.circle")
                .font(.system(size: 30))
                .foregroundColor(.red)
                .padding()
            Text("账单添加失败，请重试")
                .font(.title)
                .foregroundColor(.red)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.5).cornerRadius(20))
        .ignoresSafeArea(.all)
       
    }
}

struct MainMenu_Previews: PreviewProvider {

//    static var testAddBill = AddBill.testAddBills()
    static var previews: some View {
        MainMenu()
    }
}
